package com.weishao.example;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.util.StopWatch;
import com.weishao.dbmapper.IDatabaseMapperEngine;
import com.weishao.dbmapper.IResultRowHandler;
import com.weishao.dbmapper.engine.DefaultMapperEngine;
import com.weishao.dbmapper.pojo.TaskMapTypeEnum;
import com.weishao.dbmapper.pojo.TaskParamEntity;
import com.weishao.dbwriter.DatabaseWriterFactory;
import com.weishao.dbwriter.IDatabaseWriter;

public class DbmapperExampleApplication {

	private static int BATCH_SIZE = 10000;
	
	/**
	 * 一对一映射测试示例
	 */
	@SuppressWarnings("serial")
	public static void testMapperOneByOne(BasicDataSource dataSource) {
		String sourceSchemaName="tang";
		String sourceTableName="some_test_user";
		String targetSchemaName = "tang";
		String taregetTableName = "some_target_user";

		IDatabaseMapperEngine mapper = new DefaultMapperEngine();
		mapper.setMapperEngineDataSource(dataSource);
		mapper.setQuietWhenCoderMapperException(true);

		IDatabaseWriter writer = DatabaseWriterFactory.createDatabaseWriter(dataSource);
		writer.prepareWrite(targetSchemaName, taregetTableName);

		Map<String, String> fieldsMapper = new HashMap<String, String>();
		// key为目的表的字段名称，value为源表(查询)的字段名称
		fieldsMapper.put("Id", "Id");
		fieldsMapper.put("SalaryNo", "SMT_SalaryNo");
		fieldsMapper.put("Name", "SMT_Name");
		fieldsMapper.put("Namespell", "SMT_Namespell");
		fieldsMapper.put("Sex", "SMT_Sex");
		fieldsMapper.put("Xbm", "SMT_Sex");
		fieldsMapper.put("Birthday", "SMT_Birthday");
		Map<String, Map<String, String>> valuesMapper = new HashMap<String, Map<String, String>>();
		// key为目的表字段名称
		valuesMapper.put("Xbm", new HashMap<String, String>() {
			{
				put("男", "M");
				put("女", "F");
			}
		});

		TaskParamEntity.TaskParamEntityBuilder taskBuilder = TaskParamEntity.builder();
		taskBuilder.mapType(TaskMapTypeEnum.OneByOne);//这里标识为一对一映射
		taskBuilder.viewSql(null);//如果一对一映射自己写了SQL语句，那模块将会使用这个SQL语句，这里只为增量映射设计使用
		taskBuilder.schemaName(sourceSchemaName);
		taskBuilder.tableName(sourceTableName);
		taskBuilder.fetchSize(BATCH_SIZE);
		taskBuilder.fieldsMapper(fieldsMapper);
		taskBuilder.valuesMapper(valuesMapper);

		StopWatch watch = new StopWatch();
		watch.start("watcher");

		mapper.runMapperTransfer(taskBuilder.build(), new IResultRowHandler() {

			private long count = 0;
			private List<Object[]> cache = new LinkedList<Object[]>();

			@Override
			public void handle(List<String> columns, Object[] record) {
				cache.add(record);
				count++;
				if (cache.size() > BATCH_SIZE) {
					doSave(columns);
				}
			}

			@Override
			public void destroy(List<String> columns) {
				if (cache.size() > 0) {
					doSave(columns);
				}

				System.out.println("total handle count: " + this.count);
			}

			private void doSave(List<String> columns) {
				long ret = writer.write(columns, cache);
				cache.clear();
				System.out.println("handle count=" + ret);
			}
		});

		watch.stop();
		System.out.println("Total elipse :" + watch.getTotalTimeSeconds() + " s");
		System.out.println(watch.prettyPrint());
	}
	
	/**
	 * 多对一映射测试示例
	 */
	@SuppressWarnings("serial")
	public static void testMapperMuiltiByOne(BasicDataSource dataSource) {
		String sourceSchemaName="tang";
		String sourceTableName="ws_user,ws_org";
		String targetSchemaName = "tang";
		String taregetTableName = "new_user";

		IDatabaseMapperEngine mapper = new DefaultMapperEngine();
		mapper.setMapperEngineDataSource(dataSource);
		mapper.setQuietWhenCoderMapperException(true);

		IDatabaseWriter writer = DatabaseWriterFactory.createDatabaseWriter(dataSource);
		writer.prepareWrite(targetSchemaName, taregetTableName);

		Map<String, String> fieldsMapper = new HashMap<String, String>();
		// key为目的表的字段名称，value为源表(查询)的字段名称
		fieldsMapper.put("number", "xgh");
		fieldsMapper.put("name", "xm");
		fieldsMapper.put("sex", "xbm");
		fieldsMapper.put("xbm", "xbm");
		fieldsMapper.put("sfzjh", "sfzjh");
		fieldsMapper.put("rysf", "rysf");
		fieldsMapper.put("sznj", "sznj");
		fieldsMapper.put("bmdm", "bmdm");
		fieldsMapper.put("parent", "pbmdm");
		Map<String, Map<String, String>> valuesMapper = new HashMap<String, Map<String, String>>();
		// key为目的表字段名称
		valuesMapper.put("sex", new HashMap<String, String>() {
			{
				put("1", "男");
				put("2", "女");
			}
		});
		
		TaskParamEntity.TaskParamEntityBuilder taskBuilder = TaskParamEntity.builder();
		taskBuilder.mapType(TaskMapTypeEnum.MultiByOne);//这里标识为多对一映射
		taskBuilder.viewSql("SELECT u.xgh,u.xm,u.xbm,u.sfzjh,u.rysf,u.sznj,u.rxnf,o.bmdm,o.bmmc,o.pbmdm from tang.ws_user u LEFT JOIN tang.ws_org o on u.bmdm=o.bmdm");
		taskBuilder.schemaName(sourceSchemaName);
		taskBuilder.tableName(sourceTableName);
		taskBuilder.fetchSize(BATCH_SIZE);
		taskBuilder.fieldsMapper(fieldsMapper);
		taskBuilder.valuesMapper(valuesMapper);

		StopWatch watch = new StopWatch();
		watch.start("watcher");

		mapper.runMapperTransfer(taskBuilder.build(), new IResultRowHandler() {

			private long count=0;
			private List<Object[]> cache = new LinkedList<Object[]>();

			@Override
			public void handle(List<String> columns, Object[] record) {
				cache.add(record);
				count++;
				if (cache.size() >= BATCH_SIZE) {
					doSave(columns);
				}
			}
			
			@Override
			public void destroy(List<String> columns) {
				if (cache.size() > 0) {
					doSave(columns);
				}
				
				System.out.println("total handle count: " + this.count);
			}

			private void doSave(List<String> columns) {
				long ret = writer.write(columns, cache);
				cache.clear();
				System.out.println("handle count=" + ret);
			}
		});

		watch.stop();
		System.out.println("Total elipse :" + watch.getTotalTimeSeconds() + " s");
		System.out.println(watch.prettyPrint());
	}

	public static void main(String[] args) {
		BasicDataSource dataSource = new BasicDataSource();
		dataSource.setDriverClassName("org.postgresql.Driver");
		dataSource.setUrl("jdbc:postgresql://172.17.207.151:5432/study");
		dataSource.setUsername("study");
		dataSource.setPassword("123456");
		dataSource.setInitialSize(5);
		dataSource.setMaxIdle(5);
		dataSource.setMinIdle(2);
		
		testMapperOneByOne(dataSource);
		//testMapperMuiltiByOne(dataSource);

		try {
			dataSource.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
